package pe.com.astech.web.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.SQLTimeoutException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.NestedRuntimeException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;

import pe.com.astech.web.bean.DetalleOrdenTrabajoBean;
import pe.com.astech.web.bean.EmpleadoBean;
import pe.com.astech.web.bean.OrdenTrabajoBean;
import pe.com.astech.web.dao.OrdenTrabajoDao;
import pe.com.astech.web.exception.DBException;
import pe.com.astech.web.util.Constantes;
import pe.com.astech.web.util.Util;

@Repository
public class OrdenTrabajoDaoImpl implements OrdenTrabajoDao {

	private JdbcTemplate jdbcTemplate;

	private static final Log log = LogFactory.getLog(OrdenTrabajoDaoImpl.class);

	@Autowired
	public void setDataSource(DataSource dataSource) {
		this.jdbcTemplate = new JdbcTemplate(dataSource);
	}

	@Override
	public List<OrdenTrabajoBean> buscarOrdenTrabajo(
			String mensajeTrazabilidad, String nroPedido, String estado) {
		String query = "select ot.id_orden_trabajo,ot.codigo_ot,ot.nombre_ot,ot.presupuesto,ot.fecha_emision,ot.fecha_entrega, "
				+ "ot.estado,ot.observacion,ot.orden_pedido_ID,ot.maquinaria_ID,op.nro_orden,ot.ejemplo from orden_trabajo ot "
				+ "inner join orden_pedido op on ot.orden_pedido_ID=op.id_orden_pedido "
				+ "inner join maquinaria tm on tm.id_maquinaria=ot.maquinaria_ID "
				+ "where op.nro_orden like :nroPedido and ot.estado like :estado";

		List<OrdenTrabajoBean> list = new ArrayList<OrdenTrabajoBean>();
		log.info(mensajeTrazabilidad + " query : " + query);
		MapSqlParameterSource parameters = new MapSqlParameterSource();
		parameters.addValue("nroPedido", "%" + nroPedido + "%");
		parameters.addValue("estado", "%" + estado + "%");

		NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(
				jdbcTemplate);
		List<Map<String, Object>> usrRows = namedParameterJdbcTemplate
				.queryForList(query, parameters);

		for (Map<String, Object> usrRow : usrRows) {

			OrdenTrabajoBean ordenTrabajoBean = new OrdenTrabajoBean();
			ordenTrabajoBean.setId_orden_trabajo(String.valueOf(usrRow
					.get("id_orden_trabajo")));
			ordenTrabajoBean.setCodigo_ot(String.valueOf(usrRow
					.get("codigo_ot")));
			ordenTrabajoBean.setNombre_ot(String.valueOf(usrRow
					.get("nombre_ot")));
			ordenTrabajoBean.setPresupuesto(String.valueOf(usrRow
					.get("presupuesto")));
			ordenTrabajoBean.setFecha_emision(String.valueOf(usrRow
					.get("fecha_emision")));
			ordenTrabajoBean.setFecha_entrega(String.valueOf(usrRow
					.get("fecha_entrega")));
			ordenTrabajoBean.setEstado(String.valueOf(usrRow.get("estado")));
			ordenTrabajoBean.setObservacion(String.valueOf(usrRow
					.get("observacion")));
			ordenTrabajoBean.setOrden_pedido_ID(String.valueOf(usrRow
					.get("orden_pedido_ID")));
			ordenTrabajoBean.setMaquinaria_ID(String.valueOf(usrRow
					.get("maquinaria_ID")));
			ordenTrabajoBean.setNro_orden_pedido(String.valueOf(usrRow
					.get("nro_orden")));
			ordenTrabajoBean.setEjemplo(String.valueOf(usrRow.get("ejemplo")));

			list.add(ordenTrabajoBean);
			log.info(mensajeTrazabilidad + " " + ordenTrabajoBean.toString());
		}
		return list;
	}

	@Override
	public String[] guardarOrdenTrabajo(String mensajeTrazabilidad,
			OrdenTrabajoBean bean) {

		String mensajeTransaccionMetodo = mensajeTrazabilidad
				+ "[guardarOrdenTrabajo] ";
		String[] respuesta = new String[Constantes.intDOS];
		String[] ordenPedidoMaquinaria = bean.getOrden_pedido_ID().split(
				Constantes.GUION);

		log.info(mensajeTrazabilidad + "  "
				+ bean.toString());
		
		log.info(mensajeTrazabilidad + " p_orden_pedido_ID "
				+ ordenPedidoMaquinaria[Constantes.intCERO]);
		log.info(mensajeTrazabilidad + " p_maquinaria_ID "
				+ ordenPedidoMaquinaria[Constantes.intUNO]);

		String queryInsert = "insert into orden_trabajo ("
				+ "codigo_ot,nombre_ot,presupuesto,fecha_emision,fecha_entrega,estado,observacion,ejemplo,orden_pedido_ID,"
				+ "maquinaria_ID) "
				+ "values (:p_codigo_ot,:p_nombre_ot,:p_presupuesto,:p_fecha_emision,:p_fecha_entrega,:p_estado,:p_observacion,:p_ejemplo,:p_orden_pedido_ID,:p_maquinaria_ID)";

		log.info(mensajeTrazabilidad + " queryInsert : " + queryInsert);
		String resultado = "";

		MapSqlParameterSource parametersInsert = new MapSqlParameterSource();
		parametersInsert.addValue("p_codigo_ot", bean.getCodigo_ot());
		parametersInsert.addValue("p_nombre_ot", bean.getNombre_ot());
		parametersInsert.addValue("p_presupuesto", bean.getPresupuesto());
		parametersInsert.addValue("p_fecha_emision", bean.getFecha_emision());
		parametersInsert.addValue("p_fecha_entrega", bean.getFecha_entrega());
		parametersInsert.addValue("p_estado", bean.getEstado());
		parametersInsert.addValue("p_observacion", bean.getObservacion());
		parametersInsert.addValue("p_ejemplo", bean.getEjemplo());
		parametersInsert.addValue("p_orden_pedido_ID",
				ordenPedidoMaquinaria[Constantes.intCERO]);
		parametersInsert.addValue("p_maquinaria_ID",
				ordenPedidoMaquinaria[Constantes.intUNO]);

		NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(
				jdbcTemplate);

		KeyHolder keyHolder = new GeneratedKeyHolder();

		namedParameterJdbcTemplate.update(queryInsert, parametersInsert,
				keyHolder);

		log.info(mensajeTransaccionMetodo + " keyHolder "
				+ keyHolder.getKey().intValue());
		
		respuesta[Constantes.intCERO] = String.valueOf(keyHolder.getKey()
				.intValue());
		
		
		String queryUpdate = "update orden_trabajo " + "set " 
				+ "codigo_ot = :codigo_ot " 
				+ "where id_orden_trabajo = :id_orden_trabajo";
		
		log.info(mensajeTrazabilidad + " queryUpdate : " + queryUpdate);
		
		MapSqlParameterSource parametersUpdate = new MapSqlParameterSource();
		parametersUpdate.addValue("codigo_ot", Util.completarCeros(keyHolder.getKey()
				.intValue()));
		parametersUpdate.addValue("id_orden_trabajo", String.valueOf(keyHolder.getKey()
				.intValue()));
		
		namedParameterJdbcTemplate.update(queryUpdate, parametersUpdate);
		
		return respuesta;
	}

	@Override
	public void guardarDetalleOrdenTrabajo(String mensajeTrazabilidad,
			DetalleOrdenTrabajoBean detalleOrdenTrabajoBean) {

		String mensajeTransaccionMetodo = mensajeTrazabilidad
				+ "[guardarDetalleOrdenTrabajo] ";
		String id_detalle_ot = detalleOrdenTrabajoBean
				.getId_detalle_orden_trabajo();

		String queryInsert = "insert into detalle_orden_trabajo (cantidad,descripcion,orden_trabajo_ID,material_ID)"
				+ "values (:p_cantidad,:p_descripcion,:p_orden_trabajo_ID,:p_material_ID)";

		String queryUpdate = "update detalle_orden_trabajo "
				+ "set cantidad = :cantidad," + "descripcion = :descripcion "
				+ "where id_detalle_orden_trabajo = :id_detalle_orden_trabajo";

		NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(
				jdbcTemplate);

		if (null == id_detalle_ot || Constantes.VACIO.equals(id_detalle_ot)) {
			log.info(mensajeTransaccionMetodo + " queryInsert : " + queryInsert);

			MapSqlParameterSource parametersInsert = new MapSqlParameterSource();
			parametersInsert.addValue("p_cantidad",
					detalleOrdenTrabajoBean.getCantidad());
			parametersInsert.addValue("p_descripcion",
					detalleOrdenTrabajoBean.getDescripcion());
			parametersInsert.addValue("p_orden_trabajo_ID",
					detalleOrdenTrabajoBean.getOrden_trabajo_id());
			parametersInsert.addValue("p_material_ID",
					detalleOrdenTrabajoBean.getMaterial_id());

			namedParameterJdbcTemplate.update(queryInsert, parametersInsert);
		} else {
			log.info(mensajeTransaccionMetodo + " queryUpdate : " + queryUpdate);

			MapSqlParameterSource parametersUpdate = new MapSqlParameterSource();
			parametersUpdate.addValue("cantidad",
					detalleOrdenTrabajoBean.getCantidad());
			parametersUpdate.addValue("descripcion",
					detalleOrdenTrabajoBean.getDescripcion());
			parametersUpdate.addValue("id_detalle_orden_trabajo",
					detalleOrdenTrabajoBean.getId_detalle_orden_trabajo());

			namedParameterJdbcTemplate.update(queryUpdate, parametersUpdate);
		}

	}

	@Override
	public OrdenTrabajoBean obtenerOTbyId(String mensajeTrazabilidad,
			String id_orden_trabajo) {
		String query = "select ot.id_orden_trabajo,ot.codigo_ot,ot.nombre_ot,ot.presupuesto,ot.fecha_emision,ot.fecha_entrega, "
				+ "ot.estado,ot.observacion,ot.orden_pedido_ID,ot.maquinaria_ID,op.nro_orden,tm.modelo,tm.nombre,c.razon_social,ot.ejemplo from orden_trabajo ot "
				+ "inner join orden_pedido op on ot.orden_pedido_ID=op.id_orden_pedido "
				+ "inner join cliente c on op.cliente_ID=c.id_cliente "
				+ "inner join maquinaria tm on tm.id_maquinaria=ot.maquinaria_ID "
				+ "where ot.id_orden_trabajo = :id_orden_trabajo";

		List<OrdenTrabajoBean> list = new ArrayList<OrdenTrabajoBean>();
		log.info(mensajeTrazabilidad + " query : " + query);
		MapSqlParameterSource parameters = new MapSqlParameterSource();
		parameters.addValue("id_orden_trabajo", id_orden_trabajo);

		NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(
				jdbcTemplate);
		List<Map<String, Object>> usrRows = namedParameterJdbcTemplate
				.queryForList(query, parameters);

		OrdenTrabajoBean ordenTrabajoBean = new OrdenTrabajoBean();

		for (Map<String, Object> usrRow : usrRows) {

			ordenTrabajoBean.setId_orden_trabajo(String.valueOf(usrRow
					.get("id_orden_trabajo")));
			ordenTrabajoBean.setCodigo_ot(String.valueOf(usrRow
					.get("codigo_ot")));
			ordenTrabajoBean.setNombre_ot(String.valueOf(usrRow
					.get("nombre_ot")));
			ordenTrabajoBean.setPresupuesto(String.valueOf(usrRow
					.get("presupuesto")));
			ordenTrabajoBean.setFecha_emision(String.valueOf(usrRow
					.get("fecha_emision")));
			ordenTrabajoBean.setFecha_entrega(String.valueOf(usrRow
					.get("fecha_entrega")));
			ordenTrabajoBean.setEstado(String.valueOf(usrRow.get("estado")));
			ordenTrabajoBean.setObservacion(String.valueOf(usrRow
					.get("observacion")));
			ordenTrabajoBean.setOrden_pedido_ID(String.valueOf(usrRow
					.get("orden_pedido_ID")));
			ordenTrabajoBean.setMaquinaria_ID(String.valueOf(usrRow
					.get("maquinaria_ID")));
			ordenTrabajoBean.setNombre_maquinaria(String.valueOf(usrRow
					.get("nombre")));
			ordenTrabajoBean.setModelo_maquinaria(String.valueOf(usrRow
					.get("modelo")));
			ordenTrabajoBean.setNro_orden_pedido(String.valueOf(usrRow
					.get("nro_orden")));
			ordenTrabajoBean.setRazon_social(String.valueOf(usrRow
					.get("razon_social")));
			ordenTrabajoBean.setEjemplo(String.valueOf(usrRow.get("ejemplo")));

			log.info(mensajeTrazabilidad + " " + ordenTrabajoBean.toString());
		}
		return ordenTrabajoBean;
	}

	@Override
	public List<DetalleOrdenTrabajoBean> obtenerDetalleOT(
			String mensajeTrazabilidad, String id_orden_trabajo) {

		String query = "select dot.id_detalle_orden_trabajo,dot.cantidad,dot.descripcion,dot.orden_trabajo_ID, "
				+ "dot.material_ID,m.nombre from detalle_orden_trabajo dot "
				+ "inner join material m on m.id_material = dot.material_ID "
				+ "where dot.orden_trabajo_ID = :id_orden_trabajo";

		List<DetalleOrdenTrabajoBean> list = new ArrayList<DetalleOrdenTrabajoBean>();
		log.info(mensajeTrazabilidad + " query : " + query);
		MapSqlParameterSource parameters = new MapSqlParameterSource();
		parameters.addValue("id_orden_trabajo", id_orden_trabajo);

		NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(
				jdbcTemplate);
		List<Map<String, Object>> usrRows = namedParameterJdbcTemplate
				.queryForList(query, parameters);

		for (Map<String, Object> usrRow : usrRows) {
			DetalleOrdenTrabajoBean detalleOrdenTrabajoBean = new DetalleOrdenTrabajoBean();
			detalleOrdenTrabajoBean.setId_detalle_orden_trabajo(String
					.valueOf(usrRow.get("id_detalle_orden_trabajo")));
			detalleOrdenTrabajoBean.setCantidad(String.valueOf(usrRow
					.get("cantidad")));
			detalleOrdenTrabajoBean.setDescripcion(String.valueOf(usrRow
					.get("descripcion")));
			detalleOrdenTrabajoBean.setNombre_material(String.valueOf(usrRow
					.get("nombre")));
			detalleOrdenTrabajoBean.setOrden_trabajo_id(String.valueOf(usrRow
					.get("orden_trabajo_ID")));
			detalleOrdenTrabajoBean.setMaterial_id(String.valueOf(usrRow
					.get("material_ID")));

			list.add(detalleOrdenTrabajoBean);
			log.info(mensajeTrazabilidad + " "
					+ detalleOrdenTrabajoBean.toString());
		}
		return list;
	}

	@Override
	public void actualizarOrdenTrabajo(String mensajeTrazabilidad,
			OrdenTrabajoBean bean) {

		String mensajeTransaccionMetodo = mensajeTrazabilidad
				+ "[actualizarOrdenTrabajo] ";
		String[] ordenPedidoMaquinaria = bean.getOrden_pedido_ID().split(
				Constantes.GUION);

		log.info(mensajeTrazabilidad + " p_orden_pedido_ID "
				+ ordenPedidoMaquinaria[Constantes.intCERO]);
		log.info(mensajeTrazabilidad + " p_maquinaria_ID "
				+ ordenPedidoMaquinaria[Constantes.intUNO]);

		String queryUpdate = "update orden_trabajo " + "set "
				+ "nombre_ot = :nombre_ot," + "presupuesto = :presupuesto,"
				+ "fecha_emision = :fecha_emision,"
				+ "fecha_entrega = :fecha_entrega," + "estado = :estado,"
				+ "ejemplo = :ejemplo," + "orden_pedido_ID = :orden_pedido_ID,"
				+ "maquinaria_ID = :maquinaria_ID "
				+ "where id_orden_trabajo = :id_orden_trabajo";

		log.info(mensajeTrazabilidad + " queryUpdate : " + queryUpdate);

		MapSqlParameterSource parametersInsert = new MapSqlParameterSource();
		parametersInsert.addValue("nombre_ot", bean.getNombre_ot());
		parametersInsert.addValue("presupuesto", bean.getPresupuesto());
		parametersInsert.addValue("fecha_emision", bean.getFecha_emision());
		parametersInsert.addValue("fecha_entrega", bean.getFecha_entrega());
		parametersInsert.addValue("estado", bean.getEstado());
		parametersInsert.addValue("ejemplo", bean.getEjemplo());
		parametersInsert.addValue("orden_pedido_ID",
				ordenPedidoMaquinaria[Constantes.intCERO]);
		parametersInsert.addValue("maquinaria_ID",
				ordenPedidoMaquinaria[Constantes.intUNO]);
		parametersInsert.addValue("id_orden_trabajo",
				bean.getId_orden_trabajo());

		NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(
				jdbcTemplate);

		namedParameterJdbcTemplate.update(queryUpdate, parametersInsert);

	}

	@Override
	public void eliminarMaterialesOT(String mensajeTrazabilidad,
			DetalleOrdenTrabajoBean detalleOrdenTrabajoBean) {

		String query = "DELETE FROM detalle_orden_trabajo WHERE id_detalle_orden_trabajo=:id_detalle_orden_trabajo";
		MapSqlParameterSource parameters = new MapSqlParameterSource();
		parameters.addValue("id_detalle_orden_trabajo",
				detalleOrdenTrabajoBean.getId_detalle_orden_trabajo());
		NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(
				jdbcTemplate);
		log.info("query : " + query);
		namedParameterJdbcTemplate.update(query, parameters);

	}

	@Override
	public List<DetalleOrdenTrabajoBean> cargarEjemploOT(
			String mensajeTrazabilidad, String maquinaria_ID) {
		
		String query = "select dot.cantidad,dot.descripcion,dot.material_ID,m.nombre " +
						"from orden_trabajo ot " +
						"inner join detalle_orden_trabajo dot on dot.orden_trabajo_ID = ot.id_orden_trabajo " +
						"inner join material m on m.id_material = dot.material_ID " +
						"where ot.maquinaria_ID=:maquinaria_ID and ot.ejemplo = 1";

		List<DetalleOrdenTrabajoBean> list = new ArrayList<DetalleOrdenTrabajoBean>();
		log.info(mensajeTrazabilidad + " query : " + query);
		MapSqlParameterSource parameters = new MapSqlParameterSource();
		parameters.addValue("maquinaria_ID", maquinaria_ID);

		NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(
				jdbcTemplate);
		List<Map<String, Object>> usrRows = namedParameterJdbcTemplate
				.queryForList(query, parameters);

		for (Map<String, Object> usrRow : usrRows) {
			DetalleOrdenTrabajoBean detalleOrdenTrabajoBean = new DetalleOrdenTrabajoBean();
			detalleOrdenTrabajoBean.setCantidad(String.valueOf(usrRow
					.get("cantidad")));
			detalleOrdenTrabajoBean.setDescripcion(String.valueOf(usrRow
					.get("descripcion")));
			detalleOrdenTrabajoBean.setNombre_material(String.valueOf(usrRow
					.get("nombre")));
			detalleOrdenTrabajoBean.setMaterial_id(String.valueOf(usrRow
					.get("material_ID")));

			list.add(detalleOrdenTrabajoBean);
			log.info(mensajeTrazabilidad + " "
					+ detalleOrdenTrabajoBean.toString());
		}
		return list;
	}
	
	@Override
	public void actualizarEjemplosOT(String mensajeTrazabilidad,
			OrdenTrabajoBean bean) {
		
		String mensajeTransaccionMetodo = mensajeTrazabilidad
				+ "[actualizarEjemplosOT] ";
		String[] ordenPedidoMaquinaria = bean.getOrden_pedido_ID().split(
				Constantes.GUION);
		
		log.info(mensajeTransaccionMetodo + "  "
				+ bean.toString());
		
		log.info(mensajeTransaccionMetodo + " p_orden_pedido_ID "
				+ ordenPedidoMaquinaria[Constantes.intCERO]);
		log.info(mensajeTransaccionMetodo + " p_maquinaria_ID "
				+ ordenPedidoMaquinaria[Constantes.intUNO]);
		
		String queryUpdate = "update orden_trabajo " +
							 "set ejemplo = :ejemplo " +
							 "where maquinaria_ID = :maquinaria_ID";
		
		log.info(mensajeTransaccionMetodo + " queryInsert : " + queryUpdate);
		
		MapSqlParameterSource parametersInsert = new MapSqlParameterSource();
		parametersInsert.addValue("ejemplo", Constantes.EJEMPLO_OT_NOOK);
		parametersInsert.addValue("maquinaria_ID",
				ordenPedidoMaquinaria[Constantes.intUNO]);
		
		NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(
				jdbcTemplate);
		
		namedParameterJdbcTemplate.update(queryUpdate, parametersInsert);
		
	}

	@Override
	public void eliminarOT(String mensajeTrazabilidad, String id_orden_trabajo) {
		// TODO Auto-generated method stub
		String mensajeTransaccionMetodo = mensajeTrazabilidad
				+ "[eliminarOT] ";
		
		log.info(mensajeTransaccionMetodo + "  id_orden_trabajo = "
				+ id_orden_trabajo);
		
		String queryDelete = "DELETE FROM orden_trabajo " +
							  "WHERE id_orden_trabajo=:id_orden_trabajo";
		
		log.info(mensajeTransaccionMetodo + " queryDelete : " + queryDelete);
		
		MapSqlParameterSource parametersInsert = new MapSqlParameterSource();
		parametersInsert.addValue("id_orden_trabajo", id_orden_trabajo);
		
		NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(
				jdbcTemplate);
		
		namedParameterJdbcTemplate.update(queryDelete, parametersInsert);
	}
	
	@Override
	public void eliminarDetalleOTbyIdOT(String mensajeTrazabilidad,
			String id_orden_trabajo) {

		String query = "DELETE FROM detalle_orden_trabajo WHERE orden_trabajo_ID=:id_orden_trabajo";
		MapSqlParameterSource parameters = new MapSqlParameterSource();
		parameters.addValue("id_orden_trabajo",id_orden_trabajo);
		NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(
				jdbcTemplate);
		log.info("query : " + query);
		namedParameterJdbcTemplate.update(query, parameters);

	}


}
